<?php

namespace addons\shopro\model;

use think\Db;
use addons\shopro\exception\Exception;
use think\Model;
use traits\model\SoftDelete;

/**
 * 活动模型
 */
class ActivityBargain extends Model
{
    use SoftDelete;

    // 表名,不含前缀
    protected $name = 'shopro_activity_bargain';
    // 自动写入时间戳字段
    protected $autoWriteTimestamp = 'int';
    // 定义时间戳字段名
    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';
    protected $deleteTime = 'deletetime';

    protected $hidden = ['createtime', 'updatetime', 'deletetime', 'goods_ids'];

    /**
     * 开始报名砍价
     * @param $bargain_id 活动ID
     * @param $goods_id 商品ID
     * @param $user_id 用户ID
     * @param $deal_money 砍价金额
     * @param $valid_time 有效时间(小时)
     * @param $user_addr_id 用户ID
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function beginToBargain($bargain_id, $goods_id, $user_id, $deal_money,$min_price, $valid_time,$user_addr_id)
    {
        //判断当前是否已经在砍价了
        $w = [
            'activity_bargain_id'=>$bargain_id,
            'goods_id' => $goods_id,
            'user_id' => $user_id,
            //'invalid_time' => ['gt', time()],
            //'is_addorder' => 0,
        ];
        $user_bargain = db('shopro_activity_bargainirg')
            ->where($w)
            ->order('id desc')
            ->find();

        if ($user_bargain && $user_bargain['invalid_time'] > time() && $user_bargain['is_addorder'] == 0) {
            throw new Exception("砍价中,不能再报名砍价");
        }


        // 配送方式为 快递 或者 自提 必须填写收货地址
        $user_address = UserAddress::where("user_id", $user_id)->find($user_addr_id);
        if ($user_addr_id == 0 || is_null($user_address)) {
            throw new Exception("请选择正确的收货地址");
        }

        $expiretime = $valid_time * 3600;

        $data['user_addr_id']        = $user_addr_id;
        $data['phone']      = $user_address->phone;
        $data['consignee']  = $user_address->consignee;
        $data['province_name'] = $user_address->province_name;
        $data['city_name']  = $user_address->city_name;
        $data['area_name']  = $user_address->area_name;
        $data['address']    = $user_address->address;
        $data['province_id'] = $user_address->province_id;
        $data['city_id']    = $user_address->city_id;
        $data['area_id']    = $user_address->area_id;

        $data['invalid_time'] = time() + $expiretime;
        $data['activity_bargain_id'] = $bargain_id;
        $data['goods_id']   = $goods_id;
        $data['user_id']    = $user_id;
        $data['deal_money'] = $deal_money;
        $data['createtime']= time();
        $data['bargain_count']  = 0;
        $data['activity_price'] = $deal_money + $min_price;
        $data['activity_min_price'] = $min_price;

        Db::name('shopro_activity_bargainirg')->insert($data);
        $insertId   = Db::name('shopro_activity_bargainirg')->getLastInsID();
        $data['id'] = $insertId;


        if ($expiretime > 0) {
            // 增加自动关闭拼团队列(如果有虚拟成团，会判断虚拟成团)
            \think\Queue::later($expiretime, '\addons\shopro\job\ActivityBargainAutoOper@expire', [
                'bargainirg' => $data,
                'bargainirg_id' => $data['id'],
            ], 'shopro');
        }

        return $data;
    }

    //查询帮忙砍价的伙伴列表
    public static function getAssistorList ( $bargainirg_id = 0){
        $data = db('shopro_activity_bargain_list')->where(['bargainirg_id'=>$bargainirg_id])->order('id desc')->select();
        return $data;
    }

    //拿砍价活动下所有商品
    public static function getActivityBargainProducts ()
    {
        $data = db('shopro_activity_bargain')
            ->alias('bar')
            ->field("bar.*,goods.image")
            ->join('shopro_goods goods','bar.goods_id = goods.id')
            ->where(['bar.deletetime'=>null])
            ->order('bar.id desc')
            ->select();

        foreach ($data as &$item){
            //图片
            $item['image'] = cdnurl($item['image'], true);
        }
        return $data;
    }

    /**
     * 每次砍都是一样的价格,平均砍价
     * @param $bargainirg_id
     * @param $sponsor_id
     * @param $user
     * $bargain_money 砍价
     * @param int $join_count
     * @return bool|float|int
     */
    public static function avgBargain($bargainirg_id, $sponsor_id, $user, $bargain_money,$join_count = 0) {
        $state = false;
        $assistor_id = $user['id'];

        $fp = fopen(RUNTIME_PATH . 'bargain_lock.txt','r');

        $try = 5;
        do {
            $lock = flock($fp,LOCK_EX);
            if(!$lock)
                usleep(5000);
        } while (!$lock && --$try >= 0) ;

        //

        if ($lock) {
            Db::startTrans();
            try {
                /*-------------*/
                //更新fa_shopro_activity_bargainirg
                $id  = 0;
                $sql = "UPDATE `fa_shopro_activity_bargainirg` 
                        SET `cut_total_money` = `cut_total_money` + $bargain_money,`deal_money` = `deal_money` - $bargain_money,`bargain_count` = `bargain_count`+ 1 
                        WHERE `id` = $bargainirg_id AND `user_id` = $sponsor_id AND `deal_money` >= $bargain_money";
                //AND `bargain_count` <= $join_count";
                $row = self::execute($sql);

                if ( $row > 0) {
                    $insert_data = [];
                    $insert_data['bargainirg_id']	= $bargainirg_id;
                    $insert_data['assistor_user_id']= $assistor_id;
                    $insert_data['bargain_money'] 	= $bargain_money;
                    $insert_data['create_time']		= time();

                    $insert_data['avatar']      = $user['avatar'];
                    $insert_data['nickname']    = $user['nickname'];
                    $id = Db::name('shopro_activity_bargain_list')->insert($insert_data);
                }
                /*-------------*/
                if ($id > 0)
                    $state = true;
                Db::commit();
            }catch(\Exception $e){
                $state = false;
                \think\Log::error("帮砍出现错误:".$e->getMessage());
                Db::rollback();
            }

            flock($fp,LOCK_UN);
            fclose($fp);
        }

        if ($state !== false ) {
            return $bargain_money;
        }
        return $state;
    }

    /**
     * 砍价相关数据操作
     *$bargainirg_id    [activity_bargainirg] 表主键id
     *$sponsor_id    砍价发起者id
     *$user          帮助砍价者
     *$min           最小值
     *$max           最大值
     *$join_count    设置要参与砍价的人数
     *return bool
     */
    public static function givePartBargain($bargainirg_id, $sponsor_id, $user, $min = 0, $max = 0,$join_count = 0) {
        $state = false;
        $assistor_id = $user['id'];

        $fp = fopen(RUNTIME_PATH . 'bargain_lock.txt','r');

        $try = 5;
        do {
            $lock = flock($fp,LOCK_EX);
            if(!$lock)
                usleep(5000);
        } while (!$lock && --$try >= 0) ;

        if ($lock) {
            Db::startTrans();
            try {
                $bargain_money = self::returnRandMoney($bargainirg_id, $min, $max, $join_count);

                /*-------------*/
                //更新fa_shopro_activity_bargainirg
                $id  = 0;
                $sql = "UPDATE `fa_shopro_activity_bargainirg` 
                        SET `cut_total_money` = `cut_total_money` + $bargain_money,`deal_money` = `deal_money` - $bargain_money,`bargain_count` = `bargain_count`+ 1 
                        WHERE `id` = $bargainirg_id AND `user_id` = $sponsor_id AND `deal_money` > $bargain_money";
                //AND `bargain_count` <= $join_count";
                $row = self::execute($sql);

                if ( $row > 0) {
                    $insert_data = [];
                    $insert_data['bargainirg_id']	= $bargainirg_id;
                    $insert_data['assistor_user_id']= $assistor_id;
                    $insert_data['bargain_money'] 	= $bargain_money;
                    $insert_data['create_time']		= time();

                    $insert_data['avatar']      = $user['avatar'];
                    $insert_data['nickname']    = $user['nickname'];
                    $id = Db::name('shopro_activity_bargain_list')->insert($insert_data);
                }
                /*-------------*/
                if ($id > 0)
                    $state = true;
                Db::commit();
            }catch(\Exception $e){
                $state = false;
                \think\Log::error("帮砍出现错误:".$e->getMessage());
                Db::rollback();
            }

            flock($fp,LOCK_UN);
            fclose($fp);
        }

        if ($state !== false ) {
            return $bargain_money;
        }
        return $state;
    }

    /**
     * 返回要砍的价格
     * @param int $bargainirg_id
     * @param int $min
     * @param int $max
     * @param int $join_count
     * @return float|int
     */
    public static function returnRandMoney ($bargainirg_id = 0, $min = 0 ,$max = 0, $join_count = 0 )
    {
        $randMoney       = self::randomFloat( $min, $max);                  //返回随机价格
        $prev_Progress   = self::getBargainirgProgress($bargainirg_id);
        $prev_bargain_count = $prev_Progress['bargain_count'];              //返回已经被砍价的次数
        $remainder = $prev_bargain_count % 3;

        $bout_count = floor($join_count / 3) * 3;  //最后一轮结束的刀数       39
        $last_num = $join_count - $bout_count;
        $avg = ($min + $max) / 2;
        $before_sum  = self::getBeforeMoney($bargainirg_id, $remainder);

        if ($prev_bargain_count >= $bout_count) {
            if ($last_num == 1){
                return $avg;
            } elseif ($last_num == 2) {
                $end = $join_count - $prev_Progress['bargain_count'] ;
                if ($end == 2) {
                    return $randMoney;
                } elseif($end == 1) {
                    return $avg * 2 - $before_sum;
                }
            }
        }
        // $remainder_num   = $join_count % 3;         //总回合数的余数
        if ($remainder > 0) {
            if ( $remainder == 1) {
                $point      = $max * 0.8;    //最大额度的80%
                $bout_sum   = 3 * $avg;
                if ($before_sum >= $point) {
                    $randMoney = self::randomFloat($min, ($bout_sum - $before_sum) / 2);
                } else {
                    $randMoney = self::randomFloat(($bout_sum - $before_sum) / 2 , $point);
                }
            }
            if ($remainder == 2) {
                $round_sum_money = 3 * $avg;
                $randMoney       = $round_sum_money - $before_sum;
            }
        }
        return $randMoney;

    }

    //拿随机价格
    public static function randomFloat($min = 0, $max = 1) {
        return round($min + mt_rand() / mt_getrandmax() * ($max - $min),2);
    }


    //通过主键id拿砍价活动表的相关信息
    public static function getBargainirgProgress($id = 0)
    {
        return db('shopro_activity_bargainirg')->find($id);
    }

    //拿到上次所砍掉的价格
    public static function getBeforeMoney ( $bargain_id = 0, $limit = 1) {
        $beforemoney_sum = 0;
        $sql = "SELECT SUM(`bargain_money`) AS beforemoney_sum FROM 
                (SELECT `bargain_money` FROM `fa_shopro_activity_bargain_list` 
                WHERE `bargainirg_id` = $bargain_id
                ORDER BY `id` DESC
                LIMIT $limit) sum";

        $res = Db::query($sql);
        if (!empty($res)) {
            $beforemoney_sum = $res[0]['beforemoney_sum'];
        }
        return $beforemoney_sum;
    }

    /**
     * 分配助力砍成功之后返回佣金
     * @param $order
     * @param $user
     */
    public static function giveBargainMoney($order,$user)
    {
        //根据ID获取助力砍记录
        $item = $order->item;
        $goods_item = $item[0];      // 助力砍只能单独购买
        $bargain_id = $goods_item['activity_id'];

        //
        $bargain = db('shopro_activity_bargain')->where(['goods_id'=>$goods_item['goods_id'],'id'=>$bargain_id])->find($bargain_id);

        //找到用户报名的砍价记录
        $bargainirg = db('shopro_activity_bargainirg')->where(['activity_bargain_id'=>$bargain['id'],'user_id'=>$user['id'],'is_addorder'=>0,'deal_money'=>0])->order('id desc')->find();
        //判断是否砍价完成

        $w = [
            'bargainirg_id'=>$bargainirg['id'],
        ];
        $list = db('shopro_activity_bargain_list')->where($w)->select();
        $userModel = new User();
        $userWalletModel = new UserWalletLog();
        foreach ($list as $item){
            //循环给佣金

            $user_id = $item['assistor_user_id'];
            $user = $userModel->find($user_id);

            DB::startTrans();
            try{
                db('user')->where(['id'=>$user['id']])->setInc('money',$item['bargain_money']);
                db('retail_user')->where(['uid'=>$user['id']])->setInc('total_income',$item['bargain_money']);
                $userWalletModel->doAdd($user, $item['bargain_money'], "zhulikan_back", $order['id'], "money", 1);

                Db::commit();
            }catch (\Exception $e){
                \think\Log::write('queue-' . get_class() . '-expire' . '：执行失败，错误信息：' . $e->getMessage());
                DB::rollback();
            }

        }

    }

    //拿砍价活动下所有商品
    public static function getBargainListByUserId($user_id)
    {
        $data = db('shopro_activity_bargain')
            ->alias('bar')
            ->field("bar.*,goods.image,sab.deal_money,sab.invalid_time,sab.id as bargainirg_id")
            ->join('shopro_activity_bargainirg sab','bar.id = sab.activity_bargain_id')
            ->join('shopro_goods goods','bar.goods_id = goods.id')
            ->where(['sab.user_id'=>$user_id])
            ->order('sab.id desc')
            ->select();

        foreach ($data as &$item){
            //图片
            $item['image'] = cdnurl($item['image'], true);
        }
        return $data;
    }

}
